package Thread;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * Created with IntelliJ IDEA.
 * Description: 线程池的模拟实现
 */
class MyThreadPool {
    //创建一个线程池，应该具备的操作和功能
    //1.确定任务形式：可以直接使用Runnable
    //2.用一定的数据结构来组织任务，可以用阻塞队列
    //3.描述每个线程的工作(不断的从任务队列中拿任务并执行)
    //4.用一定的数据结构来组织线程，可以直接使用顺序表存
    //5.线程池有了，任务队列有了，就要允许程序猿向线程池注册任务进来，单独写一个public方法来传任务
    //6.最后任务传进来了，开始执行：构造方法，创建num个线程，把每个都启动，并把线程都存到线程池中

    //1.先确定任务形式
    private Runnable runnable;
    //2.规定组织任务的数据结构，直接使用阻塞队列
    private BlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();
    //3.创建线程，使用继承Thread的方式
    //  每个线程都干一件事，不断的从任务队列中取任务并执行
    private static class Work extends Thread {
        private BlockingDeque<Runnable> queue = null;
        public Work(BlockingDeque<Runnable> queue) {
            this.queue = queue;
        }
        @Override
        public void run() {
            while(true) {
                //由于外面私有成员任务队列取不到，因此我们向内部类的构造方法中传递这个队列
                try {
                    Runnable work = queue.take();
                    work.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    //4.组织线程，使用线性表
    private List<Work> works = new LinkedList<>();

    //5.线程池有了，任务队列有了，接下来让程序猿传任务进来
    public void submit(Runnable runnable){
        try {
            queue.put(runnable);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    //6.任务已经准备好了，让线程池开始工作，直接放在构造方法中
    public MyThreadPool(int num) {
        for (int i = 0; i < num; i++) {
            //创建num个线程(每个线程需要任务列表的参数)，并将这些线程启动，放在顺序表works里
            Work work = new Work(queue);
            work.start();
            works.add(work);
        }
    }

}

public class ThreadDemo30 {
    public static void main(String[] args) {
        MyThreadPool pool = new MyThreadPool(8);
        for(int i = 0; i < 100; i++) {
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello");
                }
            });
        }
    }
}
